1 /* 2 * The MIT License (MIT) 3 * 4 * Copyright (c) 2014 Devisualization (Richard Andrew Cattermole) 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to deal 8 * in the Software without restriction, including without limitation the rights 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 * copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in all 14 * copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 * SOFTWARE. 23 */ 24 module devisualization.util.opengl.shaders.defs; 25 import devisualization.util.opengl.function_wrappers; 26 import gl3n.linalg; 27 deprecated("de_util:opengl is going to die"): 28 29 class ShaderProgram { 30 private { 31 uint id_; 32 } 33 34 this(string vert, string frag=null, string geom=null) { 35 import std.typecons : scoped; 36 37 if (frag !is null && geom !is null) { 38 auto vertS = scoped!Shader(vert, ShaderTypes.VertexShader); 39 auto fragS = scoped!Shader(frag, ShaderTypes.FragmentShader); 40 auto geomS = scoped!Shader(geom, ShaderTypes.GeometryShader); 41 this(vertS, fragS, geomS); 42 } else if (frag !is null) { 43 auto vertS = scoped!Shader(vert, ShaderTypes.VertexShader); 44 auto fragS = scoped!Shader(frag, ShaderTypes.FragmentShader); 45 this(vertS, fragS, null); 46 } else if (geom !is null) { 47 auto vertS = scoped!Shader(vert, ShaderTypes.VertexShader); 48 auto geomS = scoped!Shader(geom, ShaderTypes.GeometryShader); 49 this(vertS, null, geomS); 50 } else { 51 auto vertS = scoped!Shader(vert, ShaderTypes.VertexShader); 52 this(vertS, null, null); 53 } 54 } 55 56 this(Shader vert = null, Shader frag = null, Shader geom = null) { 57 // allocate the program 58 id_ = glCreateProgram(); 59 if (vert !is null) 60 attach(vert, false); 61 if (frag !is null) 62 attach(frag, false); 63 if (geom !is null) 64 attach(geom, false); 65 link(); 66 bind(); 67 } 68 69 ~this() { 70 // destroy the program 71 glDeleteProgram(id_); 72 } 73 74 void attach(Shader shader, bool linkCall = true) { 75 // attach the shader 76 glAttachShader(id_, shader.id); 77 if (linkCall) 78 link(); 79 } 80 81 void detach(Shader shader) { 82 glDetachShader(id_, shader.id); 83 link(); 84 } 85 86 uint getAttribute(string name) { 87 return glGetAttribLocation(id_, name); 88 } 89 90 uint getUniform(string name) { 91 return glGetUniformLocation(id_, name); 92 } 93 94 @property { 95 uint id() { return id_; } 96 } 97 98 void bind() { 99 glUseProgram(id_); 100 } 101 102 void uniform(string name, mat2 value, bool transpose = false) { 103 bind(); 104 glUniformMatrix2(getUniform(name), transpose, cast(float[])value.matrix); 105 } 106 107 void uniform(string name, mat3 value, bool transpose = false) { 108 bind(); 109 glUniformMatrix3(getUniform(name), transpose, cast(float[])value.matrix); 110 } 111 112 void uniform(string name, mat4 value, bool transpose = false) { 113 bind(); 114 glUniformMatrix4(getUniform(name), transpose, cast(float[])value.matrix); 115 } 116 117 void uniform(string name, vec2 value) { 118 bind(); 119 glUniform(getUniform(name), cast(float[])value.vector); 120 } 121 122 void uniform(string name, vec3 value) { 123 bind(); 124 glUniform(getUniform(name), cast(float[])value.vector); 125 } 126 127 void uniform(string name, vec4 value) { 128 bind(); 129 glUniform(getUniform(name), cast(float[])value.vector); 130 } 131 132 void uniform(string name, float[2] value) { 133 bind(); 134 glUniform(getUniform(name), value); 135 } 136 137 void uniform(string name, float[4] value) { 138 bind(); 139 glUniform(getUniform(name), value); 140 } 141 142 void uniform(string name, bool value) { 143 bind(); 144 glUniform(getUniform(name), value); 145 } 146 147 void uniform(string name, int[2] value) { 148 bind(); 149 glUniform(getUniform(name), value); 150 } 151 152 void uniform(string name, int[4] value) { 153 bind(); 154 glUniform(getUniform(name), value); 155 } 156 157 void uniform(string name, int value) { 158 bind(); 159 glUniform(getUniform(name), value); 160 } 161 162 private { 163 void link() { 164 glLinkProgram(id_); 165 166 int res; 167 glGetProgram(id_, ProgramObjects.LinkStatus, res); 168 if (!res) 169 throw new Exception(getInfoLog()); 170 } 171 172 string getInfoLog() { 173 int res; 174 glGetProgram(id_, ProgramObjects.InfoLogStatus, res); 175 176 if (res > 0) { 177 return glGetProgramInfoLog(id_); 178 } 179 return ""; 180 } 181 } 182 } 183 184 class Shader { 185 private { 186 //ShaderObj id_; 187 uint id_; 188 ShaderTypes type_; 189 } 190 191 /** 192 * Given either the source or filename(asset loader). 193 */ 194 this(string source, ShaderTypes type) { 195 // create 196 id_ = glCreateShader(type_); 197 opAssign(source); 198 type_ = type; 199 compile(); 200 } 201 202 ~this() { 203 glDeleteShader(id_); 204 } 205 206 void opAssign()(string source) { 207 // assign 208 glShaderSource(id_, source); 209 compile(); 210 } 211 212 @property { 213 ShaderTypes type() { return type_; } 214 uint id() { return id_; } 215 } 216 217 private { 218 void compile() { 219 // compile 220 glCompileShader(id_); 221 222 int res; 223 glGetShader(id_, ShaderObjects.CompileStatus, res); 224 if (!res) 225 throw new Exception(getInfoLog()); 226 } 227 228 string getInfoLog() { 229 int res; 230 glGetShader(id_, ShaderObjects.InfoLogLength, res); 231 232 if (res > 0) { 233 return glGetProgramInfoLog(id_); 234 } 235 return ""; 236 } 237 } 238 }